#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import datetime
import argparse
import urllib.request
import threading
from threading import Timer
import bs4
from bs4 import BeautifulSoup as BS

gs_home = 'http://gs.tju.edu.cn/'
gs_url = gs_home + 'xwsy/xwtz.htm'

def get_today(is_chinese=True):
    # import time
    # import locale
    # locale.setlocale(local.LC_CTYPE, 'zh_CN.UTF-8')
    # return time.strftime('%y年%-m月%-d日')
    today = datetime.date.today()

    return '{year}年{month}月{day}日'.format(year=today.year, month=today.month, day=today.day)


def parse_gs_page():
    """
    解析学位通知网页内容
    """
    page_info = urllib.request.urlopen(gs_url)
    page_data = page_info.read().decode('utf-8')
    page_html = BS(page_data, 'html.parser')
    
    # 提取更新日期
    more_news_text = page_html.find_all(name='div',attrs={"class":"about-more-news-text"})
    update_date = None
    for news_text in more_news_text:
        news_text_info = news_text.get_text(strip=True)
        flag1, flag2 = '截至' in news_text_info, '截止' in news_text_info
        if "论文送审平台反馈评阅意见份数" in news_text_info and (flag1 or flag2):
            update_date = news_text_info.split('截至')[1].split('日')[0] + '日' if flag1 else (news_text_info.split('截止')[1].split('日')[0] + '日')
            print('更新日期:', update_date)
    if update_date is None:
        print('ERROR! CANNOT OBTAIN THE UPDATE DATE!')
        exit(1)
    
    for link in page_html.find_all('a'):
        info_link = link.get('href')
        info_text = link.get_text(strip=True)
        # print(info_text.split('截至'))
        # update_date = info_text.split('截至')[1].split('日')[0] + '日'
        if '论文送审平台反馈评阅意见统计表' in info_text:
            # 返回评审意见网址和更新日期信息
            return gs_home + info_link[2:], update_date


def parse_comments_page(comments_link, target_stdno):
    """
    解析反馈评阅意见网页内容
    """
    comments_info = urllib.request.urlopen(comments_link)
    comments_data = comments_info.read().decode('utf-8')
    comments_html = BS(comments_data, 'html.parser')
    
    comments_table = []
    target_info = None

    # 解析HTML表格内容
    for idx, tr in enumerate(comments_html.find_all('tr')):
        if idx != 0:
            tds = tr.find_all('td')
            # 获取学号等信息
            serialNo = str(tds[0].contents[0])
            
            # 移除标题行
            if '序号' in serialNo:
                continue

            stdNo, department = tds[1].contents[1].text[1:-1], tds[2].contents[1].text[1:-1]
            commentsNum = tds[3].contents[1].text[1:-1] \
                if len(tds[3].contents) > 1 and isinstance(tds[3].contents[1], bs4.element.Tag) else str(tds[3].contents[0][1:-1])
            # print("学院: {}，学号：{}，反馈意见数目：{}\n".format(department, stdNo, commentsNum))
            
            comment_dict = {
                'SerialNo': serialNo, 
                'Department': department,
                'StdNo': stdNo,
                '#Comments': commentsNum
            }
            comments_table.append(comment_dict)
            
            if target_stdno in stdNo:
                target_info = comment_dict

    # 返回查询目标信息和所有评阅意见信息
    return target_info, comments_table


def mac_notification(comment_contents):
    """
    MacOS系统浮窗通知，已验证。
    """
    from subprocess import call
    cmd = 'display notification \"{contents}\" with title \"{title}\"'.format(contents=comment_contents,
                                                                              title='反馈评阅意见份数')

    call(['osascript', '-e', cmd])


def win_notification(comment_contents):
    """
    Reference: https://blog.csdn.net/yueyue200830/article/details/104270913
    参考别人设计实现，未验证。
    """
    from win10toast import ToastNotifier
    toaster.show_toast('反馈评阅意见份数',
                       comment_contents,
                       icon_path=None,
                       duration=10,
                       threaded=True)
    
    while toaster.notification_active():
        time.sleep(1)


def linux_notification(comment_contents):
    """
    Reference: https://blog.csdn.net/dyx1024/article/details/7447443
    参考别人设计实现，未验证。
    """
    import pynotify
    pynotify.init('Bubble@Linux')
    bubble_notify = pynotify.Notification('反馈评阅意见份数',
                                          comment_contents)

    bubble_notify.show()


def notification(comments_num):
    """
    查询信息通知
    """
    import platform
    
    sysstr = platform.system()
    if isinstance(comments_num, int):
        comment_contents = "{} 份".format(comments_num)
        print("已收到评审意见数：{} 份".format(comments_num))
    else:
        comment_contents = "无评阅意见或已完成评审"
        print("无评阅意见或已完成评审")

    if sysstr == 'Windows':
        win_notification(comment_contents=comment_contents)
    elif sysstr == 'Linux':
        linux_notification(comment_contents=comment_contents)
    elif sysstr == 'Darwin':
        mac_notification(comment_contents=comment_contents)
    else:
        raise RuntimeError("Unknown platform.")


def comments_monitor(weekday, interval):
    # 信息仅在周一、三、五更新
    timer_flag = True
    if weekday in [0, 2, 4]:
        comment_link, update_date = parse_gs_page()
        # update_date = "2021年4月9日"
        if update_date == get_today():
            timer_flag = False
            target_info, comments_table = parse_comments_page(comment_link, args.stdno[0])
            if target_info is None:
                print("无评阅意见或已完成评审")
                notification("无评阅意见或已完成评审")
            else:
                print("已收到评阅意见{}份".format(int(target_info['#Comments'])))
                notification(int(target_info['#Comments']))

    if timer_flag:
        print("Active #thread:", threading.activeCount())
        # global monitor_timer
        monitor_timer = Timer(interval, comments_monitor, kwargs={'weekday':weekday, 'interval':interval})
        monitor_timer.start()


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='天津大学学位论文评阅意见监控脚本。')
    parser.add_argument('--stdno', dest='stdno', type=str, nargs='+', required=True,
                        help='要查询的学号。')
    parser.add_argument('--hour', dest='hour', default=0, type=int, help='间隔时长，单位小时。')
    parser.add_argument('--minute', dest='minute', default=0, type=int, help='间隔时长，单位分钟。')
    parser.add_argument('--second', dest='second', default=0, type=int, help='间隔时长，单位秒。')
    
    args = parser.parse_args()

    print('当前查询的学号为：', args.stdno[0])
    
    # 获取今天对应的周几信息
    weekday = datetime.date.today().weekday()
    print('今日日期：{}（周{}）'.format(get_today(), weekday+1))
    
    # 间隔时长
    interval = args.hour * 60 * 60 + args.minute * 60 + args.second
    print('查询间隔为{}小时{}分{}秒，共{}秒'.format(args.hour, args.minute, args.second, interval))
    
    comments_monitor(weekday, interval)
